﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once
#include "IPolygon.h"
#include "IPolyCurve.h"
#include <vector>
#include <tuple>
#include "EnLoopsState.h"
#include "GeometryErrorCode.h"


namespace gcmp
{
    class ICurve2d;
    class ICurve3d;
    class IBody;
    class ILine3d;

    class ICurveOperate
    {
    public:
        virtual ~ICurveOperate() {};

        /// \brief      根据二维曲线集合，生成多个多边形
        /// \param  Curve2dlist  二维曲线集合
        /// \param polygonList 的集合
        /// \param polygonLoopCoedgeIndexToOriginCrvIndexMap  polygonList中某一曲线所在的polygon序号，
        ///                                                       Loop序号和Coedge序号与它在原始曲线集合(curve2dlist)中序号的对应关系
        /// \param  dDistEpsilon 距离误差
        /// \return     polygonList多边形中环的状态
        virtual EnLoopsState Curve2dlistToPolygonLists(
            const std::vector<const ICurve2d*>& curve2dlist,
            std::vector<OwnerPtr<IPolygon>>& polygonList,
            std::map<std::tuple<int, int, int>, int>& polygonLoopCoedgeIndexToOriginCrvIndexMap,
            double dDistEpsilon)const = 0;

        virtual EnLoopsState Curve2dlistToPolygonLists(
            const std::vector<const ICurve2d*>& curve2dlist,
            std::vector<OwnerPtr<IPolygon>>& polygonList,
            std::map<std::tuple<int, int, int>, int>& polygonLoopCoedgeIndexToOriginCrvIndexMap,
            double dDistEpsilon,
            std::vector<const ICurve2d*>& errorCurves) const = 0;

        /// \brief      根据二维曲线集合，生成多个逆时针，首尾连接，并且封闭的 CoedgeList 的集合
        /// \param  Curve2dlist  二维曲线集合
        /// \param Coedgelists  CoedgeList 的集合
        /// \param curve2dMap   原始的 Curve2d 与 CoedgeList 中的 Curve2d 的对应关系
        /// \param  dDistEpsilon 距离误差
        /// \param errorCurves 返回值不合法时对应的存在问题的两条边（不封闭的环边，自交的环边，相交的环边），指针是参数Coedgelists中的指针，不需要单独释放
        /// \return     环的状态
        virtual EnLoopsState Curve2dlistToCoedgelists(const std::vector<const ICurve2d*>& curve2dlist, std::vector<OwnerPtr<IPolyCurve>> &coedgelists,
            std::map<ICurve2d*, ICurve2d*> &curve2dMap, double dDistEpsilon, std::pair<ICurve2d*, ICurve2d*> *errorCurves = nullptr) const = 0;

        
        /// \brief      三维曲线扣减封闭体得到三维曲线集合
        /// \param  const ICurve3d* pGmICurve3d               三维曲线
        /// \param  const IBody* pGmBody                       封闭的体
        /// \param  bool bOnReserved                            是否保留在体上的曲线部分
        /// \param std::vector<OwnerPtr<ICurve3d>> &ressultCurves    扣减得到的三维曲线集合
        virtual bool Subtract(const ICurve3d* pGmICurve3d, const IBody* pGmBody, bool bOnReserved, std::vector<OwnerPtr<ICurve3d>>& ressultCurves) const = 0;


        /// \brief      三维曲线交封闭体得到三维曲线集合
        /// \param  const ICurve3d* pGmICurve3d     三维曲线
        /// \param  const IBody* pGmBody            封闭的体
        /// \param  bool bOnReserved                是否保留在体上的曲线部分
        /// \param  resultCurves                    相交得到的三维曲线集合
        virtual bool Intersect(const ICurve3d* pGmICurve3d, const IBody* pGmBody, bool bOnReserved, std::vector<OwnerPtr<ICurve3d>>& resultCurves) const = 0;


        /// \brief    曲线在指定参数分割
        /// \param pGmICurve3d 原始曲线
        /// \param param 指定参数,参数必须在曲线参数域范围内
        /// \param opCurve3dLeft 参数域范围为[min,param]的曲线
        /// \param opCurve3dRight 参数域范围为[param，max]的曲线
        /// \return    是否分割成功：true = 是；false = 否
        virtual bool Subdivide(const ICurve3d* pGmICurve3d, double param, OwnerPtr<ICurve3d> &opCurve3dLeft, OwnerPtr<ICurve3d> &opCurve3dRight) const = 0;

        
        /// \brief    截取指定参数范围内的曲线
        /// \param pGmICurve3d 原始曲线
        /// \param paramStart 指定起始参数,参数必须在曲线参数域范围内
        /// \param paramEnd  指定结束参数,参数必须在曲线参数域范围内
        /// \param opCurve3dTrimed 参数域范围为[paramStart,paramEnd]的曲线
        /// \return    是否截取成功：true = 是；false = 否
        virtual bool Trim(const ICurve3d* pGmICurve3d, double paramStart, double paramEnd, OwnerPtr<ICurve3d> &opCurve3dTrimed) const = 0;

        
        /// \brief   计算曲线外一点到曲线的最近的垂点
        /// \param const ICurve2d* pGmICurve2d       二维曲线
        /// \param const Vector2d &inputPoint        曲线外一点
        /// \param Vector2d &perpPoint              如果有多个垂点，取离点inputPoint最近的垂点
        /// \param  double dEpsilon                  精度
        /// \return      true = 成功；false = 失败
        virtual bool GetPerpendicularPoint(const ICurve2d* pGmICurve2d, const Vector2d &inputPoint, Vector2d &perpPoint, double dEpsilon) const = 0;
    
        
        /// \brief  曲线按首尾连接的方式排序，包括封闭情况
        /// \param[in] unsortedCurves  未排序的曲线组
        /// \param[out] sortedCurves  排序的曲线组
        /// \param[out] sortedIndexes  排序的序号
        /// \return true: 成功; false: 1)三分叉; 2) 输入曲线存在首尾未连接的情形
        virtual bool CreateSequencedCurves(const std::vector<const ICurve3d*>& unsortedCurves,
            std::vector<OwnerPtr<ICurve3d>>& sortedCurves,
            std::vector<int>& sortedIndexes) const = 0;

        /// \brief  给定一组二维曲线，搜索多段线
        ///
        /// 不考虑自交；超过2条线共点，与其共点的所有线都以单条PolyCurve线输出; 两条线端点共点，但不是首尾相连，会将其中一条线反向
        ///
        /// \param[in] pCurve2dList        二维曲线数组
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] opPolyCurves       搜到的多段线集合，一个IPolyCurve是一组首尾相连的线，可以是闭合的，也可以不是闭合的。
        /// \param[out] originalCurveIndices 搜到的多段线对应的原始线（pCurve2dList ）索引集合，集合size和opPolyCurves的size大小一样。
        /// \return 成功返回true，失败返回false
        virtual bool SearchPolyCurves(const std::vector<const ICurve2d*> &pCurve2dList, double dDistanceEpsilon, std::vector<OwnerPtr<IPolyCurve>>& opPolyCurves, std::vector<std::vector<int>>* originalCurveIndices)const = 0;
    
        /// \brief 输入一条多段线和一个多段线数组，查找多段线数组中与这条多段线全等的多段线。支持自交多段线，不区分反向与乱序。
        ///
        /// \param[in] pPolygonCurve 输入的一条多段线
        /// \param[in] polyCurveArray 输入的多段线数组
        /// \param[out] 与输入多段线全等的多段线的索引和对应的变换矩阵
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] errorIndexArray 非法 PolyCurve 的索引
        /// \return 无非法情况，返回true。其他情况返回false，输出的全等多段线信息可用
        virtual bool SearchCongruentPolyCurves(const IPolyCurve* pPolygonCurve, const std::vector<const IPolyCurve*>& polyCurveArray, std::vector<std::pair<int, Matrix4d>>& indexAndMatrix4d, double dDistanceEpsilon, std::vector<int>* errorIndexArray) const = 0;

        /// \brief 输入一组多段线，将其中全等的多段线分类。支持自交多段线，不区分反向与乱序。
        ///
        /// \param[in] polyCurveArray 输入的一组多段线
        /// \param[out] 分类的结果。输出结果是一个数组，数组中每个元素都代表一种全等多段线。
        /// 每个元素的第一个参数是这种全等多段线在输入的多段线数组中第一次出现的索引。
        /// 每个元素的第二个参数是其他全等多段线的索引和变换矩阵。
        /// \param[in] dDistanceEpsilon    距离容差
        /// \param[out] errorIndexArray 非法 PolyCurve 的索引
        /// \return 无非法情况，返回true。其他情况返回false，输出的全等多段线信息可用
        virtual bool ClassifyCongruentPolyCurves(const std::vector<const IPolyCurve*>& polyCurveArray, std::vector<std::pair<int, std::vector<std::pair<int, Matrix4d>>>>& classification, double dDistanceEpsilon, std::vector<int>* errorIndexArray) const = 0;

        /// \brief 输入一个目标几何数组和多个几何数组，查找与这个目标几何数组全等的几何数组，输入的几何中只支持polygon、polycurve 、curve2d
        ///
        /// \param[in] geometries 输入的目标几何数组
        /// \param[in] geometriesArray 输入的几何数组集合
        /// \param[out] 与输入目标几何数组全等的几何数组的索引和对应的变换矩阵
        /// \param[out] errorIndexArray 输入的几何数组集合中非法的索引
        /// \param[in] dDistanceEpsilon    距离容差
        /// \return 无非法情况，返回true。其他情况返回false，输出的全等信息可用
        virtual bool SearchCongruentGeometrys(const std::vector<const IGeometry*>& geometries, const std::vector<std::vector<const IGeometry*>>& geometriesArray, std::vector<std::pair<int, Matrix4d>>& indexAndMatrix4d, double dDistanceEpsilon, std::vector<int>* errorIndexArray) const = 0;

        /// \brief 输入几何数组集合，将其中全等的几何数组分类
        ///
        /// \param[in] geometriesArray 输入的输入的几何数组集合
        /// \param[out] 分类的结果。输出结果是一个数组，数组中每个元素都代表一种全等的几何数组。
        /// 每个元素的第一个参数是这种全等几何数组在输入的几何数组集合中第一次出现的索引。
        /// 每个元素的第二个参数是其他全等几何数组集合的索引和变换矩阵。
        /// \param[out] errorIndexArray 非法 PolyCurve 的索引
        /// \param[in] dDistanceEpsilon    距离容差
        /// \return 无非法情况，返回true。其他情况返回false，输出的全等多段线信息可用
        virtual bool ClassifyCongruentGeometrys(const std::vector<std::vector<const IGeometry*>>& geometriesArray, std::vector<std::pair<int, std::vector<std::pair<int, Matrix4d>>>>& classification, double dDistanceEpsilon, std::vector<int>* errorIndexArray) const = 0;
        
        /// \brief 输入一个线框体或者单点体，计算出其与另外一个线框体的所有切线
        ///
        /// \param[in] pFirstBody 输入三维线框体或者单点体
        /// \param[in] pSecondBody 输入线框体或者单点体
        /// \param[in] distEpsilon    距离容差
        /// \param[out] opTangentLines 所有切线
        /// \return 处理结果
        virtual GeometryErrorCode CalculateTangentLines(const IBody* pFirstBody, const IBody* pSecondBody, double distEpsilon,std::vector<OwnerPtr<ILine3d>>& opTangentLines) const = 0;
    };
}